package person.twj.jwt.core.security.util;

import io.jsonwebtoken.Claims;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import person.twj.jwt.core.security.constant.TokenConstants;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class TokenUtil {
    public static String createRefreshToken(UserToken userToken) {
        long exp = System.currentTimeMillis() + TokenConstants.REFRESH_EXPIRES_IN;

        return createToken(userToken, exp);
    }

    //@TODO security: 2. 生成token
    public static String createToken(UserToken userToken) {
        long exp = System.currentTimeMillis() + TokenConstants.EXPIRES_IN;

        return createToken(userToken, exp);

    }

    public static String createToken(UserToken userToken, long exp) {
        Map<String, Object> claimsMap = new HashMap<String, Object>();
        claimsMap.put(UserToken.Fields.userId, userToken.getUserId());// 用户id
        claimsMap.put(UserToken.Fields.username, userToken.getUsername());// 用户名
        claimsMap.put(UserToken.Fields.exp, exp);// 有效时间
        claimsMap.put(UserToken.Fields.authorities, userToken.getAuthorities());// 有效时间

        return JwtUtils.createToken(claimsMap);
    }
    // 解析token，并验证
    // 异常：BadCredentialsException、CredentialsExpiredException
    public static UserToken parseTokenInfo(String token) throws BadCredentialsException,CredentialsExpiredException{
        Claims claims = null;
        if(StringUtils.isBlank(token)){
            throw new BadCredentialsException("令牌不正确！");
        }

        try {
            claims = JwtUtils.parseToken(token);
        }catch (Exception e){
            log.error("token解析失败，"+e.getMessage(),e);
            // 有令牌，但解析出来的令牌失效，或者令牌错误
            throw new BadCredentialsException("令牌不正确！");
        }

        if (claims.get(UserToken.Fields.userId)==null
                ||claims.get(UserToken.Fields.username)==null
                ||claims.get(UserToken.Fields.exp)==null){
            throw new BadCredentialsException("令牌验证不正确！");
        }


        UserToken userToken = new UserToken(
                (Long) claims.get(UserToken.Fields.userId),
                (String) claims.get(UserToken.Fields.username),
                "1", // 没用的参数，但又不能为空，为空则报错，所以随便写个1
                new ArrayList<>());
//        userToken.setUserId((Long) claims.get(UserToken.Fields.userId));
        userToken.setExp((Long) claims.get(UserToken.Fields.exp));


        if (TokenUtil.verify(userToken)) {
            throw new CredentialsExpiredException("令牌已过期！");
        }
        return userToken;
    }

    public static boolean verify(UserToken userToken) {
        Long exp = userToken.getExp();
        if(exp!=null&&System.currentTimeMillis()<exp){
            return false;
        }else{
            return true;
        }
    }
}
